package com.imut.lagain.service.impl;

import com.imut.lagain.service.IEmailService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import jakarta.mail.MessagingException;
import jakarta.mail.internet.MimeMessage;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.CompletableFuture;

/**
 * 邮件服务实现类
 * 提供邮件发送功能
 */
@Service
@RequiredArgsConstructor
public class EmailServiceImpl implements IEmailService {
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(EmailServiceImpl.class);

    
    private final JavaMailSender mailSender;
    private final TemplateEngine templateEngine;
    
    @Value("${spring.mail.username}")
    private String fromEmail;
    
    @Value("${app.name:时光胶囊}")
    private String appName;
    
    @Value("${app.domain:localhost:8080}")
    private String appDomain;
    /**
     * 发送简单文本邮件
     * @param to 收件人
     * @param subject 主题
     * @param content 内容
     * @return 是否发送成功
     */
    public boolean sendSimpleEmail(String to, String subject, String content) {
        try {
            if (!isValidEmail(to)) {
                log.warn("邮箱地址无效: {}", to);
                return false;
            }
            
            SimpleMailMessage message = new SimpleMailMessage();
            message.setFrom(fromEmail);
            message.setTo(to);
            message.setSubject(subject);
            message.setText(content);
            message.setSentDate(new java.util.Date());
            
            mailSender.send(message);
            return true;
        } catch (Exception e) {
            log.error("简单邮件发送失败: to={}, subject={}", to, subject, e);
            return false;
        }
    }
    
    /**
     * 发送HTML邮件
     * @param to 收件人
     * @param subject 主题
     * @param htmlContent HTML内容
     * @return 是否发送成功
     */
    public boolean sendHtmlEmail(String to, String subject, String htmlContent) {
        try {
            if (!isValidEmail(to)) {
                log.warn("邮箱地址无效: {}", to);
                return false;
            }
            
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8");
            
            helper.setFrom(fromEmail);
            helper.setTo(to);
            helper.setSubject(subject);
            helper.setText(htmlContent, true);
            helper.setSentDate(new java.util.Date());
            
            mailSender.send(message);
            return true;
        } catch (MessagingException e) {
            log.error("HTML邮件发送失败: to={}, subject={}", to, subject, e);
            return false;
        }
    }
    
    /**
     * 使用模板发送邮件
     * @param to 收件人
     * @param subject 主题
     * @param templateName 模板名称
     * @param variables 模板变量
     * @return 是否发送成功
     */
    public boolean sendTemplateEmail(String to, String subject, String templateName, Map<String, Object> variables) {
        try {
            if (!isValidEmail(to)) {
                log.warn("邮箱地址无效: {}", to);
                return false;
            }
            Context context = new Context();
            if (variables != null) {
                variables.forEach(context::setVariable);
            }
            context.setVariable("appName", appName);
            context.setVariable("appDomain", appDomain);
            context.setVariable("currentTime", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            String htmlContent = templateEngine.process(templateName, context);
            
            return sendHtmlEmail(to, subject, htmlContent);
        } catch (Exception e) {
            log.error("模板邮件发送失败: to={}, subject={}, template={}", to, subject, templateName, e);
            return false;
        }
    }
    
    /**
     * 异步发送邮件
     * @param to 收件人
     * @param subject 主题
     * @param content 内容
     * @return CompletableFuture
     */
    public CompletableFuture<Boolean> sendEmailAsync(String to, String subject, String content) {
        return CompletableFuture.supplyAsync(() -> sendSimpleEmail(to, subject, content));
    }
    
    /**
     * 异步发送HTML邮件
     * @param to 收件人
     * @param subject 主题
     * @param htmlContent HTML内容
     * @return CompletableFuture
     */
    public CompletableFuture<Boolean> sendHtmlEmailAsync(String to, String subject, String htmlContent) {
        return CompletableFuture.supplyAsync(() -> sendHtmlEmail(to, subject, htmlContent));
    }
    
    /**
     * 异步发送模板邮件
     * @param to 收件人
     * @param subject 主题
     * @param templateName 模板名称
     * @param variables 模板变量
     * @return CompletableFuture
     */
    public CompletableFuture<Boolean> sendTemplateEmailAsync(String to, String subject, String templateName, Map<String, Object> variables) {
        return CompletableFuture.supplyAsync(() -> sendTemplateEmail(to, subject, templateName, variables));
    }
    /**
     * 发送验证码邮件
     * @param to 收件人
     * @param code 验证码
     * @return 是否发送成功
     */
    public boolean sendVerificationCode(String to, String code) {
        String subject = appName + " - 邮箱验证码";
        Map<String, Object> variables = Map.of(
            "code", code,
            "expireMinutes", 5
        );
        return sendTemplateEmail(to, subject, "verification-code", variables);
    }
    
    /**
     * 发送欢迎邮件
     * @param to 收件人
     * @param username 用户名
     * @return 是否发送成功
     */
    public boolean sendWelcomeEmail(String to, String username) {
        String subject = "欢迎加入" + appName;
        Map<String, Object> variables = Map.of(
            "username", username
        );
        return sendTemplateEmail(to, subject, "welcome", variables);
    }
    
    /**
     * 发送密码重置邮件
     * @param to 收件人
     * @param username 用户名
     * @param resetToken 重置令牌
     * @return 是否发送成功
     */
    public boolean sendPasswordResetEmail(String to, String username, String resetToken) {
        String subject = appName + " - 密码重置";
        String resetUrl = "https://" + appDomain + "/reset-password?token=" + resetToken;
        Map<String, Object> variables = Map.of(
            "username", username,
            "resetUrl", resetUrl,
            "expireHours", 24
        );
        return sendTemplateEmail(to, subject, "password-reset", variables);
    }
    
    /**
     * 发送胶囊开启通知邮件
     * @param to 收件人
     * @param username 用户名
     * @param capsuleTitle 胶囊标题
     * @param openTime 开启时间
     * @return 是否发送成功
     */
    public boolean sendCapsuleOpenNotification(String to, String username, String capsuleTitle, LocalDateTime openTime) {
        String subject = appName + " - 时光胶囊开启提醒";
        Map<String, Object> variables = Map.of(
            "username", username,
            "capsuleTitle", capsuleTitle,
            "openTime", openTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm"))
        );
        return sendTemplateEmail(to, subject, "capsule-open-notification", variables);
    }
    
    /**
     * 异步发送简单文本邮件
     * @param to 收件人
     * @param subject 主题
     * @param content 内容
     * @return CompletableFuture<Boolean>
     */
    @Override
    public CompletableFuture<Boolean> sendSimpleEmailAsync(String to, String subject, String content) {
        return CompletableFuture.supplyAsync(() -> sendSimpleEmail(to, subject, content));
    }
    
    /**
     * 发送验证码邮件
     * @param to 收件人
     * @param username 用户名
     * @param verificationCode 验证码
     * @return 是否发送成功
     */
    @Override
    public boolean sendVerificationEmail(String to, String username, String verificationCode) {
        Map<String, Object> variables = Map.of(
                "username", username,
                "verificationCode", verificationCode,
                "appName", appName
        );
        
        return sendTemplateEmail(to, "验证码 - " + appName, "verification-code", variables);
    }
    
    /**
     * 发送胶囊即将开启提醒邮件
     * @param to 收件人
     * @param username 用户名
     * @param capsuleTitle 胶囊标题
     * @param openTime 开启时间
     * @param daysLeft 剩余天数
     * @return 是否发送成功
     */
    @Override
    public boolean sendCapsuleOpenReminder(String to, String username, String capsuleTitle, LocalDateTime openTime, int daysLeft) {
        String subject = appName + " - 时光胶囊即将开启";
        Map<String, Object> variables = Map.of(
            "username", username,
            "capsuleTitle", capsuleTitle,
            "openTime", openTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm")),
            "daysLeft", daysLeft
        );
        return sendTemplateEmail(to, subject, "capsule-open-reminder", variables);
    }
    
    /**
     * 发送账户安全通知邮件
     * @param to 收件人
     * @param username 用户名
     * @param action 操作类型
     * @param ip IP地址
     * @param location 位置
     * @return 是否发送成功
     */
    public boolean sendSecurityNotification(String to, String username, String action, String ip, String location) {
        String subject = appName + " - 账户安全通知";
        Map<String, Object> variables = Map.of(
            "username", username,
            "action", action,
            "ip", ip != null ? ip : "未知",
            "location", location != null ? location : "未知",
            "time", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"))
        );
        return sendTemplateEmail(to, subject, "security-notification", variables);
    }
    
    /**
     * 发送系统维护通知邮件
     * @param to 收件人
     * @param username 用户名
     * @param maintenanceTime 维护时间
     * @param duration 维护时长
     * @param reason 维护原因
     * @return 是否发送成功
     */
    public boolean sendMaintenanceNotification(String to, String username, LocalDateTime maintenanceTime, String duration, String reason) {
        String subject = appName + " - 系统维护通知";
        Map<String, Object> variables = Map.of(
            "username", username,
            "maintenanceTime", maintenanceTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm")),
            "duration", duration,
            "reason", reason
        );
        return sendTemplateEmail(to, subject, "maintenance-notification", variables);
    }
    
    /**
     * 发送安全警报邮件
     * @param to 收件人
     * @param username 用户名
     * @param alertType 警报类型
     * @param alertContent 警报内容
     * @param alertTime 警报时间
     * @return 是否发送成功
     */
    public boolean sendSecurityAlert(String to, String username, String alertType, String alertContent, LocalDateTime alertTime) {
        String subject = appName + " - 安全警报";
        Map<String, Object> variables = Map.of(
            "username", username,
            "alertType", alertType,
            "alertContent", alertContent,
            "alertTime", alertTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"))
        );
        return sendTemplateEmail(to, subject, "security-alert", variables);
    }
    
    /**
     * 发送系统通知邮件
     * @param to 收件人
     * @param username 用户名
     * @param title 通知标题
     * @param content 通知内容
     * @return 是否发送成功
     */
    public boolean sendSystemNotification(String to, String username, String title, String content) {
        Map<String, Object> variables = Map.of(
                "username", username,
                "title", title,
                "content", content,
                "appName", appName
        );
        
        return sendTemplateEmail(to, title + " - " + appName, "system-notification", variables);
    }
    
    /**
     * 发送数据导出完成通知邮件
     * @param to 收件人
     * @param username 用户名
     * @param downloadUrl 下载链接
     * @param expireTime 过期时间
     * @return 是否发送成功
     */
    public boolean sendDataExportNotification(String to, String username, String downloadUrl, LocalDateTime expireTime) {
        String subject = appName + " - 数据导出完成";
        Map<String, Object> variables = Map.of(
            "username", username,
            "downloadUrl", downloadUrl,
            "expireTime", expireTime.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm"))
        );
        return sendTemplateEmail(to, subject, "data-export-notification", variables);
    }
    /**
     * 验证邮箱地址格式
     * @param email 邮箱地址
     * @return 是否有效
     */
    private boolean isValidEmail(String email) {
        if (!StringUtils.hasText(email)) {
            return false;
        }
        return email.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
    }
    
    /**
     * 获取邮件发送状态
     * @return 邮件服务是否可用
     */
    public boolean isEmailServiceAvailable() {
        try {
            return mailSender != null && StringUtils.hasText(fromEmail);
        } catch (Exception e) {
            log.error("检查邮件服务可用性失败", e);
            return false;
        }
    }
    
    /**
     * 批量发送邮件
     * @param recipients 收件人列表
     * @param subject 主题
     * @param content 内容
     * @return 发送成功的数量
     */
    public int sendBatchEmails(String[] recipients, String subject, String content) {
        int successCount = 0;
        for (String recipient : recipients) {
            if (sendSimpleEmail(recipient, subject, content)) {
                successCount++;
            }
        }
        return successCount;
    }
    
    /**
     * 异步批量发送邮件
     * @param recipients 收件人列表
     * @param subject 主题
     * @param content 内容
     * @return CompletableFuture
     */
    public CompletableFuture<Integer> sendBatchEmailsAsync(String[] recipients, String subject, String content) {
        return CompletableFuture.supplyAsync(() -> sendBatchEmails(recipients, subject, content));
    }
}

